package com.zd.mock.liukejun;

import com.github.javafaker.Faker;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class TravelRouteDataGenerator {
    private static final String DB_URL = "jdbc:mysql://hadoop102:3306/zhengzhou_tourism_business?useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;

    // 扩展路线类型包含三日游
    private static final String[] ROUTE_TYPES = {"一日游", "两日游", "三日游", "主题游"};

    // 郑州特色景点名称
    private static final String[] ZHENGZHOU_ATTRACTIONS = {
            "少林寺", "黄河风景区", "河南博物院", "郑州方特欢乐世界", "康百万庄园",
            "郑州海洋馆", "郑州绿博园", "黄帝故里", "郑州美术馆", "郑州动物园",
            "郑州植物园", "郑州科技馆", "郑州城隍庙", "郑州二七纪念塔", "郑州博物馆"
    };

    // 路线主题关键词
    private static final String[] ROUTE_THEMES = {
            "文化", "历史", "自然", "美食", "亲子", "夜游",
            "经典", "摄影", "探险", "休闲", "研学", "红色"
    };

    public static void main(String[] args) {
        int count = 100; // 默认生成100条数据
        LocalDateTime startTime = LocalDateTime.now().minusYears(1);
        LocalDateTime endTime = LocalDateTime.now();

        // 解析命令行参数
        if (args.length >= 1) {
            count = Integer.parseInt(args[0]);
        }
        if (args.length >= 4) {
            startTime = LocalDateTime.of(
                    Integer.parseInt(args[1]),
                    Integer.parseInt(args[2]),
                    Integer.parseInt(args[3]),
                    0, 0);
        }
        if (args.length >= 7) {
            endTime = LocalDateTime.of(
                    Integer.parseInt(args[4]),
                    Integer.parseInt(args[5]),
                    Integer.parseInt(args[6]),
                    23, 59);
        }

        generateData(count, startTime, endTime);
    }

    static class TravelRoute {
        String routeName;
        String routeType;
        String description;
        String attractions; // JSON格式字符串
        double durationHours;
        double basePrice;
        LocalDateTime createTime;
        LocalDateTime updateTime;
    }

    public static void generateData(int count, LocalDateTime startTime, LocalDateTime endTime) {
        Faker faker = new Faker(Locale.CHINA);
        List<TravelRoute> routes = new ArrayList<>();
        Set<String> usedRouteNames = new HashSet<>(); // 确保路线名称唯一

        for (int i = 0; i < count; i++) {
            TravelRoute route = new TravelRoute();

            // 生成唯一路线名称：景点名/主题 + 路线类型
            String routeName;
            int attempts = 0;
            do {
                String attraction = ZHENGZHOU_ATTRACTIONS[faker.random().nextInt(ZHENGZHOU_ATTRACTIONS.length)];
                String theme = ROUTE_THEMES[faker.random().nextInt(ROUTE_THEMES.length)];
                String type = faker.options().option(ROUTE_TYPES);

                // 50%概率使用景点名称，50%使用主题
                if (faker.random().nextBoolean()) {
                    routeName = attraction + (type.equals("一日游") ? "" : type);
                } else {
                    routeName = theme + type;
                }
                attempts++;
            } while (usedRouteNames.contains(routeName) && attempts < 10); // 防止无限循环

            if (attempts >= 10) {
                routeName += "-" + (i + 1); // 添加序号确保唯一
            }

            usedRouteNames.add(routeName);
            route.routeName = routeName;

            // 随机选择路线类型
            route.routeType = faker.options().option(ROUTE_TYPES);

            // 根据路线类型生成描述
            route.description = generateDescription(route.routeName, route.routeType, faker);

            // 生成景点ID数组(JSON格式)
            route.attractions = generateAttractionsJson(faker);

            // 根据路线类型生成不同时长
            route.durationHours = generateDuration(route.routeType, faker);

            // 根据路线类型生成合理价格
            route.basePrice = generatePrice(route.routeType, faker);

            // 生成随机创建时间
            route.createTime = randomLocalDateTime(faker, startTime, endTime);

            // 更新时间在创建时间之后
            route.updateTime = randomLocalDateTime(faker,
                    route.createTime,
                    endTime.isAfter(LocalDateTime.now()) ? LocalDateTime.now() : endTime);

            routes.add(route);
        }

        // 批量插入数据库
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);

            String sql = "INSERT INTO travel_routes " +
                    "(route_name, route_type, description, attractions, duration_hours, base_price, create_time, update_time) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";

            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < routes.size(); i++) {
                    TravelRoute route = routes.get(i);
                    pstmt.setString(1, route.routeName);
                    pstmt.setString(2, route.routeType);
                    pstmt.setString(3, route.description);
                    pstmt.setString(4, route.attractions);
                    pstmt.setDouble(5, route.durationHours);
                    pstmt.setDouble(6, route.basePrice);
                    pstmt.setTimestamp(7, Timestamp.valueOf(route.createTime));
                    pstmt.setTimestamp(8, Timestamp.valueOf(route.updateTime));
                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0) {
                        pstmt.executeBatch();
                    }
                }
                pstmt.executeBatch();
                conn.commit();
                System.out.println("成功插入" + count + "条旅游路线数据");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // 生成符合示例的描述
    private static String generateDescription(String routeName, String routeType, Faker faker) {
        String[] verbs = {"体验", "探索", "欣赏", "发现", "畅游", "感受"};
        String[] features = {"文化魅力", "自然风光", "历史遗迹", "美食盛宴", "亲子乐趣", "夜景之美", "艺术氛围"};

        String verb = verbs[faker.random().nextInt(verbs.length)];
        String feature = features[faker.random().nextInt(features.length)];

        if (routeType.equals("一日游")) {
            return verb + routeName + "的" + feature + "，一日尽享郑州精华";
        } else if (routeType.equals("两日游")) {
            return "深度" + verb + routeName + "，两天领略郑州多元" + feature;
        } else if (routeType.equals("三日游")) {
            return "全方位" + verb + routeName + "，三日沉浸式体验郑州" + feature;
        } else {
            return "特色" + verb + routeName + "的" + feature + "之旅";
        }
    }

    // 生成景点ID数组(JSON格式)
    private static String generateAttractionsJson(Faker faker) {
        // 随机选择2-5个景点
        int count = 2 + faker.random().nextInt(4);
        Set<Integer> attractions = new TreeSet<>();

        while (attractions.size() < count) {
            attractions.add(1 + faker.random().nextInt(15)); // 景点ID范围1-15
        }

        return "[" + attractions.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(",")) + "]";
    }

    // 根据路线类型生成合理时长
    private static double generateDuration(String routeType, Faker faker) {
        switch (routeType) {
            case "一日游":
                return 6.0 + faker.random().nextDouble() * 4.0; // 6-10小时
            case "两日游":
                return 16.0 + faker.random().nextDouble() * 4.0; // 16-20小时
            case "三日游":
                return 24.0 + faker.random().nextDouble() * 6.0; // 24-30小时
            case "主题游":
                return 3.0 + faker.random().nextDouble() * 5.0; // 3-8小时
            default:
                return 6.0;
        }
    }

    // 根据路线类型生成合理价格
    private static double generatePrice(String routeType, Faker faker) {
        switch (routeType) {
            case "一日游":
                return 150 + faker.random().nextDouble() * 150; // 150-300元
            case "两日游":
                return 400 + faker.random().nextDouble() * 300; // 400-700元
            case "三日游":
                return 800 + faker.random().nextDouble() * 200; // 800-1000元
            case "主题游":
                return 100 + faker.random().nextDouble() * 100; // 100-200元
            default:
                return 200;
        }
    }

    private static LocalDateTime randomLocalDateTime(Faker faker, LocalDateTime start, LocalDateTime end) {
        ZonedDateTime startZoned = start.atZone(ZoneId.systemDefault());
        ZonedDateTime endZoned = end.atZone(ZoneId.systemDefault());

        long startEpoch = startZoned.toInstant().toEpochMilli();
        long endEpoch = endZoned.toInstant().toEpochMilli();

        java.util.Date startDate = new java.util.Date(startEpoch);
        java.util.Date endDate = new java.util.Date(endEpoch);

        long randomEpoch = faker.date().between(startDate, endDate).getTime();

        return LocalDateTime.ofInstant(
                java.time.Instant.ofEpochMilli(randomEpoch),
                ZoneId.systemDefault()
        );
    }
}